package lex.mxbeans.ui;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import javax.swing.table.AbstractTableModel;

import org.lex.utils.MethodNameFormatter;

import lex.mxbeans.utils.MXBeansUtils;
import lex.mxbeans.utils.ObjectUtils;

public class MXBeanTableModel extends AbstractTableModel
{
	private static final String[] EMPTY_ATTRIBUTES = new String[0];
	private static final Object[] EMPTY_VALUES = new Object[0];
	private static final String[] COLUMN_NAMES = { "Name", "Value" };
	// --------------------------------------------------------------
	private final Object bean;
	private String[] attributes = EMPTY_ATTRIBUTES;
	private Object[] values = EMPTY_VALUES;

	public MXBeanTableModel( Object bean )
	{
		this.bean = bean;
		this.loadData( bean );
	}

	public Object getValue( int row )
	{
		if( row < values.length )
			return values[row];
		else
			return null;
	}

	public void reload()
	{
		this.loadData( bean );
	}

	private void loadData( Object bean )
	{
		Class<?> clz = bean.getClass();
		clz = MXBeansUtils.findSuperClass( clz );
		if( null == clz )
			clz = bean.getClass();
		Method[] methods = clz.getMethods();
		List<Method> list = new ArrayList<Method>();
		for( Method m : methods )
			if( 0 == m.getParameterTypes().length
					&& false == Void.class.isAssignableFrom( m.getReturnType() ) )
				list.add( m );
		this.attributes = new String[list.size()];
		this.values = new Object[this.attributes.length];
		for( int i = 0, n = values.length; i < n; i++ )
		{
			Method m = list.get( i );
			this.attributes[i] = MethodNameFormatter.format( m.getName() );
			try
			{
				this.values[i] = m.invoke( bean, EMPTY_VALUES );
			}
			catch( Exception e )
			{
				// e.printStackTrace();
				this.values[i] = "";
			}
		}
		this.fireTableDataChanged();
	}

	@Override
	public Class<?> getColumnClass( int column )
	{
		if( 0 == column )
			return String.class;
		else
			return Object.class;
	}

	@Override
	public String getColumnName( int column )
	{
		return COLUMN_NAMES[column];
	}

	public int getColumnCount()
	{
		return COLUMN_NAMES.length;
	}

	@Override
	public int getRowCount()
	{
		return values.length;
	}

	@Override
	public Object getValueAt( int row, int column )
	{
		if( 0 == column )
			return attributes[row];
		else
			return ObjectUtils.toString( values[row] );
	}
}
